<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>테스트에서 보일러플레이트 줄이기 | Vue 테스팅 핸드북</title>
    <meta name="description" content="">
    <link rel="icon" href="https://lmiller1990.github.io/vue-testing-handbook/img/favicon.png">
  <meta property="og:title" content="Vue Testing Handbook">
  <meta property="og:description" content="Vue testing handbook">
  <meta property="og:type" content="website">
  <meta property="og:url" content="https://lmiller1990.github.io/vue-testing-handbook/">
  <meta property="og:image" content="https://lmiller1990.github.io/vue-testing-handbook/img/og.png">
    
    <link rel="preload" href="/vue-testing-handbook/assets/css/0.styles.99f2ca3b.css" as="style"><link rel="preload" href="/vue-testing-handbook/assets/js/app.14051834.js" as="script"><link rel="preload" href="/vue-testing-handbook/assets/js/3.119a321e.js" as="script"><link rel="preload" href="/vue-testing-handbook/assets/js/2.94957ecd.js" as="script"><link rel="preload" href="/vue-testing-handbook/assets/js/38.2a809ae1.js" as="script"><link rel="prefetch" href="/vue-testing-handbook/assets/js/10.7b1750c8.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/100.87c02eb0.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/101.9f86f8af.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/102.7cf5b3b5.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/103.9a447cc0.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/104.d960f455.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/105.42aa8c19.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/106.fa067e24.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/107.f6145328.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/108.4251a9d9.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/109.6e04b4aa.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/11.c9a15d65.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/110.203be49f.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/111.e66d4c1a.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/112.d5cf2637.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/113.0e1df8ea.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/114.b1d0a5f5.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/115.d21ab6a2.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/116.e13d34ff.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/117.532bedf9.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/118.b99c8d4d.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/119.97666be8.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/12.8ec4d737.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/120.e5fbc47b.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/121.2d6cedde.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/122.7dc3c3fc.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/123.82fcb804.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/124.affd46d3.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/125.10d1ddcb.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/126.8ca1978a.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/127.7b76e158.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/128.e0d8fdce.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/129.e861e49f.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/13.96ee585a.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/130.474092c4.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/131.71e4509c.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/132.b48fe96d.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/133.9268758a.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/134.6a042ef6.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/135.6df261f9.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/136.8aab4165.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/137.60d15690.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/138.29f827fd.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/139.e8db710e.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/14.522b77b9.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/140.8a3b2b26.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/141.cd5f96df.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/142.04a47072.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/143.ac0cb5e1.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/144.c69a73ac.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/15.2f00de2d.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/16.d120a376.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/17.9260e267.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/18.4e3a9d5e.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/19.bfe7cfa3.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/20.52828530.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/21.4d92035b.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/22.49a88bda.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/23.79de1f16.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/24.f45f108e.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/25.48371e8a.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/26.bc7a5470.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/27.49bfeced.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/28.b697055e.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/29.0ef469da.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/30.bd209efe.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/31.ddf8aa10.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/32.95ec3267.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/33.52cf0ebc.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/34.73b1ca03.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/35.be79f171.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/36.52a4dcd2.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/37.a02e83c0.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/39.31de0194.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/4.a86536d1.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/40.4a3cfcb7.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/41.db485265.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/42.8c4375ac.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/43.2f241bb5.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/44.43539973.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/45.619b76a6.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/46.00e17cc1.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/47.faf51fac.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/48.840de9e5.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/49.3410da74.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/5.d3ebdf21.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/50.647913c0.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/51.4990b428.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/52.85ff4209.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/53.7bbf915a.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/54.1fc8316d.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/55.374436d3.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/56.40ebbbe6.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/57.40d9cc46.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/58.37ab0bcf.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/59.8df2efac.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/6.637082cf.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/60.326b4bdd.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/61.449fcfe0.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/62.f05ac3d6.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/63.e1723f7e.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/64.5b9e17ef.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/65.52e8ce24.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/66.cbdf653b.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/67.522e5bfd.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/68.1c27735b.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/69.1f5624e9.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/7.43089f9d.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/70.49fd6b50.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/71.20acc429.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/72.715f4620.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/73.ac123d7d.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/74.59a869d0.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/75.772485ad.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/76.b887e73a.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/77.70e54ee3.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/78.2306c3e7.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/79.e01a6cd1.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/8.4c4cdaa7.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/80.c12fc82f.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/81.44ef90b7.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/82.ff3143a2.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/83.22084435.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/84.485c66f4.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/85.d8afef97.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/86.2ba55e96.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/87.d5642266.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/88.3ad1f8ac.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/89.e370d2fc.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/9.a0f31be6.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/90.2c039dfb.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/91.2c1dd586.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/92.571cd8ae.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/93.b88ae6f6.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/94.16000348.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/95.79a96428.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/96.c86f8cad.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/97.bc1d6c91.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/98.34c6a547.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/99.e1174558.js">
    <link rel="stylesheet" href="/vue-testing-handbook/assets/css/0.styles.99f2ca3b.css">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/vue-testing-handbook/ko/" class="home-link router-link-active"><!----> <span class="site-name">Vue 테스팅 핸드북</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Select language" class="dropdown-title"><span class="title">다른 언어로 보기</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/vue-testing-handbook/reducing-boilerplate-in-tests.html" class="nav-link">English</a></li><li class="dropdown-item"><!----> <a href="/vue-testing-handbook/v3/reducing-boilerplate-in-tests.html" class="nav-link">v3</a></li><li class="dropdown-item"><!----> <a href="/vue-testing-handbook/ja/" class="nav-link">日本語</a></li><li class="dropdown-item"><!----> <a href="/vue-testing-handbook/ru/reducing-boilerplate-in-tests.html" class="nav-link">Русский (Vue.js 2)</a></li><li class="dropdown-item"><!----> <a href="/vue-testing-handbook/v3/ru/reducing-boilerplate-in-tests.html" class="nav-link">Русский (Vue.js 3)</a></li><li class="dropdown-item"><!----> <a href="/vue-testing-handbook/zh-CN/" class="nav-link">简体中文</a></li><li class="dropdown-item"><!----> <a href="/vue-testing-handbook/ko/reducing-boilerplate-in-tests.html" class="nav-link router-link-exact-active router-link-active">한국어</a></li></ul></div></div> <a href="https://github.com/lmiller1990/vue-testing-handbook" target="_blank" rel="noopener noreferrer" class="repo-link">
    GitHub
    <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><a href="https://vuejs-course.com/" target="_blank"><img id="ad" src="https://raw.githubusercontent.com/lmiller1990/vue-testing-handbook/master/src/.vuepress/public/composition.png" alt="vuejs-course banner"></a> <br> <div class="info"><small>
    Hi! Get $10 off my
    <a href="https://vuejs-course.com/" target="_blank">new</a> <a href="https://vuejs-course.com/" target="_blank">course</a> <a href="https://vuejs-course.com/" target="_blank">on</a> <a href="https://vuejs-course.com/" target="_blank">Vue.js 3</a>,
    <a href="https://vuejs-course.com/" target="_blank">TypeScript and</a>,
    <a href="https://vuejs-course.com/" target="_blank">testing</a>,
    with the discount code VUEJS_COURSE_10_OFF.
    </small></div> <nav class="nav-links"><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Select language" class="dropdown-title"><span class="title">다른 언어로 보기</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/vue-testing-handbook/reducing-boilerplate-in-tests.html" class="nav-link">English</a></li><li class="dropdown-item"><!----> <a href="/vue-testing-handbook/v3/reducing-boilerplate-in-tests.html" class="nav-link">v3</a></li><li class="dropdown-item"><!----> <a href="/vue-testing-handbook/ja/" class="nav-link">日本語</a></li><li class="dropdown-item"><!----> <a href="/vue-testing-handbook/ru/reducing-boilerplate-in-tests.html" class="nav-link">Русский (Vue.js 2)</a></li><li class="dropdown-item"><!----> <a href="/vue-testing-handbook/v3/ru/reducing-boilerplate-in-tests.html" class="nav-link">Русский (Vue.js 3)</a></li><li class="dropdown-item"><!----> <a href="/vue-testing-handbook/zh-CN/" class="nav-link">简体中文</a></li><li class="dropdown-item"><!----> <a href="/vue-testing-handbook/ko/reducing-boilerplate-in-tests.html" class="nav-link router-link-exact-active router-link-active">한국어</a></li></ul></div></div> <a href="https://github.com/lmiller1990/vue-testing-handbook" target="_blank" rel="noopener noreferrer" class="repo-link">
    GitHub
    <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></nav>  <ul class="sidebar-links"><li><a href="/vue-testing-handbook/ko/" class="sidebar-link">환영합니다</a></li><li><a href="/vue-testing-handbook/ko/setting-up-for-tdd.html" class="sidebar-link">TDD를 위한 설정하기</a></li><li><a href="/vue-testing-handbook/ko/rendering-a-component.html" class="sidebar-link">컴포넌트 렌더하기</a></li><li><a href="/vue-testing-handbook/ko/components-with-props.html" class="sidebar-link">props 테스트하기</a></li><li><a href="/vue-testing-handbook/ko/computed-properties.html" class="sidebar-link">computed 프로퍼티</a></li><li><a href="/vue-testing-handbook/ko/simulating-user-input.html" class="sidebar-link">사용자 입력 시연하기</a></li><li><a href="/vue-testing-handbook/ko/testing-emitted-events.html" class="sidebar-link">emitted 이벤트 테스트하기</a></li><li><a href="/vue-testing-handbook/ko/mocking-global-objects.html" class="sidebar-link">전역 객체 모킹하기</a></li><li><a href="/vue-testing-handbook/ko/stubbing-components.html" class="sidebar-link">컴포넌트 스터빙</a></li><li><a href="/vue-testing-handbook/ko/finding-elements-and-components.html" class="sidebar-link">엘리먼트와 컴포넌트 찾기</a></li><li><a href="/vue-testing-handbook/ko/testing-vuex.html" class="sidebar-link">Vuex 테스트하기</a></li><li><a href="/vue-testing-handbook/ko/vuex-mutations.html" class="sidebar-link">Vuex - 뮤테이션</a></li><li><a href="/vue-testing-handbook/ko/vuex-actions.html" class="sidebar-link">Vuex - 액션</a></li><li><a href="/vue-testing-handbook/ko/vuex-getters.html" class="sidebar-link">Vuex - 게터</a></li><li><a href="/vue-testing-handbook/ko/vuex-in-components.html" class="sidebar-link">컴포넌트 내에 있는 Vuex - $state와 게터</a></li><li><a href="/vue-testing-handbook/ko/vuex-in-components-mutations-and-actions.html" class="sidebar-link">컴포넌트 내에 있는 Vuex - 뮤테이션과 액션</a></li><li><a href="/vue-testing-handbook/ko/vue-router.html" class="sidebar-link">Vue 라우터</a></li><li><a href="/vue-testing-handbook/ko/composition-api.html" class="sidebar-link">컴포지션 API</a></li><li><a href="/vue-testing-handbook/ko/reducing-boilerplate-in-tests.html" class="active sidebar-link">보일러플레이트 줄이기</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/vue-testing-handbook/ko/reducing-boilerplate-in-tests.html#테스트에서-보일러플레이트-줄이기" class="sidebar-link">테스트에서 보일러플레이트 줄이기</a></li><li class="sidebar-sub-header"><a href="/vue-testing-handbook/ko/reducing-boilerplate-in-tests.html#posts-컴포넌트" class="sidebar-link">Posts 컴포넌트</a></li><li class="sidebar-sub-header"><a href="/vue-testing-handbook/ko/reducing-boilerplate-in-tests.html#vuex-vuerouter-팩토리-함수" class="sidebar-link">Vuex/VueRouter 팩토리 함수</a></li><li class="sidebar-sub-header"><a href="/vue-testing-handbook/ko/reducing-boilerplate-in-tests.html#테스트-리팩토링-하기-전" class="sidebar-link">테스트 (리팩토링 하기 전)</a></li><li class="sidebar-sub-header"><a href="/vue-testing-handbook/ko/reducing-boilerplate-in-tests.html#커스텀-createtestvue-함수" class="sidebar-link">커스텀 createTestVue 함수</a></li><li class="sidebar-sub-header"><a href="/vue-testing-handbook/ko/reducing-boilerplate-in-tests.html#createwrapper-메서드-정의하기" class="sidebar-link">createWrapper 메서드 정의하기</a></li><li class="sidebar-sub-header"><a href="/vue-testing-handbook/ko/reducing-boilerplate-in-tests.html#초기-vuex-상태-설정하기" class="sidebar-link">초기 Vuex 상태 설정하기</a></li><li class="sidebar-sub-header"><a href="/vue-testing-handbook/ko/reducing-boilerplate-in-tests.html#개선사항" class="sidebar-link">개선사항</a></li><li class="sidebar-sub-header"><a href="/vue-testing-handbook/ko/reducing-boilerplate-in-tests.html#결론" class="sidebar-link">결론</a></li></ul></li><li><a href="/vue-testing-handbook/ko/jest-mocking-modules.html" class="sidebar-link">Jest - 모듈 모킹하기</a></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h2 id="테스트에서-보일러플레이트-줄이기"><a href="#테스트에서-보일러플레이트-줄이기" class="header-anchor">#</a> 테스트에서 보일러플레이트 줄이기</h2> <blockquote><p>이 글은 <a href="https://vuejs-course.com/screencasts/reducing-duplication-in-tests.html?ref=vth" target="_blank" rel="noopener noreferrer">Vue.js Courses<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>에서 스크린캐스트(코딩하는 화면 같이 컴퓨터 화면을 녹화한 비디오)로 이용할 수 있습니다. <a href="https://vuejs-course.com/screencasts/reducing-duplication-in-tests.html?ref=vth" target="_blank" rel="noopener noreferrer">여기<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>를 확인해주세요.</p></blockquote> <p>보통은 컴포넌트의 새 복사본을 가지고 각각의 유닛 테스트를 진행하는 게 이상적입니다. 더 나아가서 여러분의 앱이 더 커지고 복잡해질수록, 컴포넌트는 많고 다양한 props를 가질 것이고, 아마 Vuetify, VueRouter나 Vuex 같은 3rd 파티 라이브러리를 여러 개 설치했을 것입니다. 이런 부분은 여러분의 테스트에 많은 보일러플레이트 코드를 야기할 수 있습니다. 보일러플레이트 코드는 테스트와 직접적으로 관련이 없는 코드를 의미합니다.</p> <p>이 글은 Vuex, VueRouter를 사용하는 컴포넌트를 가지고, 유닛 테스트를 위한 설정 코드의 양을 줄이는 일을 도와주는 몇 가지 패턴을 설명합니다.</p> <p>이 페이지에서 설명한 테스트의 소스 코드는 <a href="https://github.com/lmiller1990/vue-testing-handbook/tree/master/demo-app/tests/unit/Posts.spec.js" target="_blank" rel="noopener noreferrer">여기<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>서 찾을 수 있습니다.</p> <h2 id="posts-컴포넌트"><a href="#posts-컴포넌트" class="header-anchor">#</a> Posts 컴포넌트</h2> <p>아래의 코드가 테스트할 컴포넌트입니다. <code>message</code> prop이 보이고, 한 태그가 받고 있습니다. 사용자가 인증된 상태이고, 몇 개의 포스트를 가지고 있다면 새로운 Post 버튼을 보여줍니다.  <code>authenticated</code>와 <code>posts</code> 객체 둘 다 Vuex 스토어에서 받습니다. 결과적으로 포스트의 링크를 보여주는 <code>router-link</code> 컴포넌트를 렌더합니다.</p> <div class="language-vue extra-class"><pre class="language-vue"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>template</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>message<span class="token punctuation">&quot;</span></span> <span class="token attr-name">v-if</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>message<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>{{ message }}<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>

    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">v-if</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>authenticated<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
      <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>router-link</span> 
        <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>new-post<span class="token punctuation">&quot;</span></span> 
        <span class="token attr-name">to</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>/posts/new<span class="token punctuation">&quot;</span></span>
      <span class="token punctuation">&gt;</span></span>
        New Post
      <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>router-link</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>

    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>h1</span><span class="token punctuation">&gt;</span></span>Posts<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>h1</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> 
      <span class="token attr-name">v-for</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>post in posts<span class="token punctuation">&quot;</span></span> 
      <span class="token attr-name">:key</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>post.id<span class="token punctuation">&quot;</span></span> 
      <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>post<span class="token punctuation">&quot;</span></span>
    <span class="token punctuation">&gt;</span></span>
      <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>router-link</span> <span class="token attr-name">:to</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>postLink(post.id)<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
        {{ post.title }}
      <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>router-link</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>template</span><span class="token punctuation">&gt;</span></span>

<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script"><span class="token language-javascript">
<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token punctuation">{</span>
  name<span class="token punctuation">:</span> <span class="token string">'Posts'</span><span class="token punctuation">,</span>
  props<span class="token punctuation">:</span> <span class="token punctuation">{</span>
    message<span class="token punctuation">:</span> String<span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>

  computed<span class="token punctuation">:</span> <span class="token punctuation">{</span>
    <span class="token function">authenticated</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span>$store<span class="token punctuation">.</span>state<span class="token punctuation">.</span>authenticated
    <span class="token punctuation">}</span><span class="token punctuation">,</span>

    <span class="token function">posts</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span>$store<span class="token punctuation">.</span>state<span class="token punctuation">.</span>posts
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>

  methods<span class="token punctuation">:</span> <span class="token punctuation">{</span>
    <span class="token function">postLink</span><span class="token punctuation">(</span><span class="token parameter">id</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">/posts/</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>id<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><p>테스트하고 싶은 부분은 아래와 같습니다.</p> <ul><li>prop을 받았을 때 <code>message</code>가 렌더되는가?</li> <li><code>posts</code>는 정확하게 렌더되는가?</li> <li>New Post 버튼은 <code>authenticated</code>가 <code>true</code>일 때는 보이고, <code>false</code>일때는 숨겨지는가?</li></ul> <p>이상적으로 테스트는 가능한 명료해야 합니다.</p> <h2 id="vuex-vuerouter-팩토리-함수"><a href="#vuex-vuerouter-팩토리-함수" class="header-anchor">#</a> Vuex/VueRouter 팩토리 함수</h2> <p>좀 더 테스트하기 편한 앱을 만들 수 있는 좋은 방법은 Vuex나 VueRouter를 위한 팩토리 함수를 내보내는 것입니다. 보통 여러분은 아래와 같은 코드를 보게 됩니다.</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// store.js</span>

<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">new</span> <span class="token class-name">Vuex<span class="token punctuation">.</span>Store</span><span class="token punctuation">(</span><span class="token punctuation">{</span> <span class="token operator">...</span> <span class="token punctuation">}</span><span class="token punctuation">)</span>

<span class="token comment">// router.js</span>
<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">new</span> <span class="token class-name">VueRouter</span><span class="token punctuation">(</span><span class="token punctuation">{</span> <span class="token operator">...</span> <span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre></div><p>일반적인 앱에서는 괜찮지만 테스트할 때는 이상적이지 않습니다. 이렇게 하면, 테스트에서 매번 스토어(store)나 라우터(router)를 사용해야 하고, 스토어나 라우터를 추출한 다른 모든 테스트에 걸쳐서 공유될 것입니다. 이상적으로 모든 컴포넌트는 스토어와 라우터의 새 복사본을 가져야 합니다.</p> <p>이 작업을 수행하는 간단한 방법은 팩토리 함수를 추출하는 것입니다. 팩토리 함수는 객체의 새 인스턴스를 반환하는 함수를 말합니다. 예를 들면 아래와 같습니다.</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// store.js</span>
<span class="token keyword">export</span> <span class="token keyword">const</span> store <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Vuex<span class="token punctuation">.</span>Store</span><span class="token punctuation">(</span><span class="token punctuation">{</span> <span class="token operator">...</span> <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token keyword">export</span> <span class="token keyword">const</span> <span class="token function-variable function">createStore</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Vuex<span class="token punctuation">.</span>Store</span><span class="token punctuation">(</span><span class="token punctuation">{</span> <span class="token operator">...</span> <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token comment">// router.js</span>
<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">new</span> <span class="token class-name">VueRouter</span><span class="token punctuation">(</span><span class="token punctuation">{</span> <span class="token operator">...</span> <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token keyword">export</span> <span class="token keyword">const</span> <span class="token function-variable function">createRouter</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Vuex<span class="token punctuation">.</span>Router</span><span class="token punctuation">(</span><span class="token punctuation">{</span> <span class="token operator">...</span> <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre></div><p>이제 메인 앱은 <code>import { store } from './store.js'</code>를 할 수 있고, 테스트에서는 <code>import { createStore } from './store.js'</code>를 하고 <code>const store = createStore()</code>로 인스턴스를 만듦으로써 매번 스토어의 새로운 복사본을 가질 수 있습니다. 라우터도 동일합니다. 이게 <code>Posts.vue</code> 예제에서 하려고 하는 일입니다. 스토어 코드는 <a href="https://github.com/lmiller1990/vue-testing-handbook/tree/master/demo-app/src/createStore.js" target="_blank" rel="noopener noreferrer">여기<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>서 라우터 코드는 <a href="https://github.com/lmiller1990/vue-testing-handbook/tree/master/demo-app/src/createRouter.js" target="_blank" rel="noopener noreferrer">여기<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>서 찾을 수 있습니다.</p> <h2 id="테스트-리팩토링-하기-전"><a href="#테스트-리팩토링-하기-전" class="header-anchor">#</a> 테스트 (리팩토링 하기 전)</h2> <p>이제 <code>Posts.vue</code>와 스토어와 라우터가 어떻게 보일지 알고, 테스트가 무엇을 해야할지 이해할 수 있습니다.</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">import</span> Vuex <span class="token keyword">from</span> <span class="token string">'vuex'</span>
<span class="token keyword">import</span> VueRouter <span class="token keyword">from</span> <span class="token string">'vue-router'</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span> mount<span class="token punctuation">,</span> createLocalVue <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'@vue/test-utils'</span>

<span class="token keyword">import</span> Posts <span class="token keyword">from</span> <span class="token string">'@/components/Posts.vue'</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span> createRouter <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'@/createRouter'</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span> createStore <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'@/createStore'</span>

<span class="token function">describe</span><span class="token punctuation">(</span><span class="token string">'Posts.vue'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token function">it</span><span class="token punctuation">(</span><span class="token string">'통과하면 메시지를 렌더한다.'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> localVue <span class="token operator">=</span> <span class="token function">createLocalVue</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    localVue<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>VueRouter<span class="token punctuation">)</span>
    localVue<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>Vuex<span class="token punctuation">)</span>

    <span class="token keyword">const</span> store <span class="token operator">=</span> <span class="token function">createStore</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token keyword">const</span> router <span class="token operator">=</span> <span class="token function">createRouter</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token keyword">const</span> message <span class="token operator">=</span> <span class="token string">'New content coming soon!'</span>
    <span class="token keyword">const</span> wrapper <span class="token operator">=</span> <span class="token function">mount</span><span class="token punctuation">(</span>Posts<span class="token punctuation">,</span> <span class="token punctuation">{</span>
      propsData<span class="token punctuation">:</span> <span class="token punctuation">{</span> message <span class="token punctuation">}</span><span class="token punctuation">,</span>
      store<span class="token punctuation">,</span> router<span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>

    <span class="token function">expect</span><span class="token punctuation">(</span>wrapper<span class="token punctuation">.</span><span class="token function">find</span><span class="token punctuation">(</span><span class="token string">&quot;#message&quot;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">text</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toBe</span><span class="token punctuation">(</span><span class="token string">'New content coming soon!'</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>

  <span class="token function">it</span><span class="token punctuation">(</span><span class="token string">'posts 렌더한다'</span><span class="token punctuation">,</span> <span class="token keyword">async</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> localVue <span class="token operator">=</span> <span class="token function">createLocalVue</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    localVue<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>VueRouter<span class="token punctuation">)</span>
    localVue<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>Vuex<span class="token punctuation">)</span>

    <span class="token keyword">const</span> store <span class="token operator">=</span> <span class="token function">createStore</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token keyword">const</span> router <span class="token operator">=</span> <span class="token function">createRouter</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token keyword">const</span> message <span class="token operator">=</span> <span class="token string">'New content coming soon!'</span>

    <span class="token keyword">const</span> wrapper <span class="token operator">=</span> <span class="token function">mount</span><span class="token punctuation">(</span>Posts<span class="token punctuation">,</span> <span class="token punctuation">{</span>
      propsData<span class="token punctuation">:</span> <span class="token punctuation">{</span> message <span class="token punctuation">}</span><span class="token punctuation">,</span>
      store<span class="token punctuation">,</span> router<span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>

    wrapper<span class="token punctuation">.</span>vm<span class="token punctuation">.</span>$store<span class="token punctuation">.</span><span class="token function">commit</span><span class="token punctuation">(</span><span class="token string">'ADD_POSTS'</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token punctuation">{</span> id<span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">,</span> title<span class="token punctuation">:</span> <span class="token string">'Post'</span> <span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
    <span class="token keyword">await</span> wrapper<span class="token punctuation">.</span>vm<span class="token punctuation">.</span><span class="token function">$nextTick</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

    <span class="token function">expect</span><span class="token punctuation">(</span>wrapper<span class="token punctuation">.</span><span class="token function">findAll</span><span class="token punctuation">(</span><span class="token string">'.post'</span><span class="token punctuation">)</span><span class="token punctuation">.</span>length<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toBe</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre></div><p>모든 조건을 완벽하게 테스트하지는 않습니다. 간단한 예제이고 시작하기에는 충분합니다. 중복과 반복에 주목하세요. 중복과 반복을 제거하겠습니다.</p> <h2 id="커스텀-createtestvue-함수"><a href="#커스텀-createtestvue-함수" class="header-anchor">#</a> 커스텀 <code>createTestVue</code> 함수</h2> <p>아래와 같이 각 테스트의 처음 다섯 줄은 동일합니다.</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">const</span> localVue <span class="token operator">=</span> <span class="token function">createLocalVue</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
localVue<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>VueRouter<span class="token punctuation">)</span>
localVue<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>Vuex<span class="token punctuation">)</span>

<span class="token keyword">const</span> store <span class="token operator">=</span> <span class="token function">createStore</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> router <span class="token operator">=</span> <span class="token function">createRouter</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</code></pre></div><p>한번 수정해보겠습니다. Vue Test Utils의 <code>createLocalVue</code>와 헷갈리지 않게, 새로 만들 함수를  <code>createTestVue</code>라고 부르겠습니다. 아래와 같은 모습입니다.</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">const</span> <span class="token function-variable function">createTestVue</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> localVue <span class="token operator">=</span> <span class="token function">createLocalVue</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  localVue<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>VueRouter<span class="token punctuation">)</span>
  localVue<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>Vuex<span class="token punctuation">)</span>

  <span class="token keyword">const</span> store <span class="token operator">=</span> <span class="token function">createStore</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token keyword">const</span> router <span class="token operator">=</span> <span class="token function">createRouter</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token keyword">return</span> <span class="token punctuation">{</span> store<span class="token punctuation">,</span> router<span class="token punctuation">,</span> localVue <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><p>이제 하나의 함수 안에 모든 로직을 캡슐화했습니다. <code>store</code>, <code>router</code> 그리고 <code>localVue</code>를 반환합니다. <code>mount</code> 함수에 인자로 넘기는 데 필요하기 때문입니다.</p> <p><code>createTestVue</code>를 사용해서 첫 번째 테스트를 리팩토링한다면, 아래와 같은 모습이 됩니다.</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token function">it</span><span class="token punctuation">(</span><span class="token string">'통과하면 메시지를 렌더한다'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> <span class="token punctuation">{</span> localVue<span class="token punctuation">,</span> store<span class="token punctuation">,</span> router <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token function">createTestVue</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token keyword">const</span> message <span class="token operator">=</span> <span class="token string">'New content coming soon!'</span>
  <span class="token keyword">const</span> wrapper <span class="token operator">=</span> <span class="token function">mount</span><span class="token punctuation">(</span>Posts<span class="token punctuation">,</span> <span class="token punctuation">{</span>
    propsData<span class="token punctuation">:</span> <span class="token punctuation">{</span> message <span class="token punctuation">}</span><span class="token punctuation">,</span>
    store<span class="token punctuation">,</span>
    router<span class="token punctuation">,</span>
    localVue
  <span class="token punctuation">}</span><span class="token punctuation">)</span>

  <span class="token function">expect</span><span class="token punctuation">(</span>wrapper<span class="token punctuation">.</span><span class="token function">find</span><span class="token punctuation">(</span><span class="token string">&quot;#message&quot;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">text</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toBe</span><span class="token punctuation">(</span><span class="token string">'New content coming soon!'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre></div><p>좀 더 명료합니다. Vuex 스토어를 사용하고 있는 두 번째 테스트를 리팩토링해 보겠습니다.</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token function">it</span><span class="token punctuation">(</span><span class="token string">'posts를 렌더한다'</span><span class="token punctuation">,</span> <span class="token keyword">async</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> <span class="token punctuation">{</span> localVue<span class="token punctuation">,</span> store<span class="token punctuation">,</span> router <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token function">createTestVue</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token keyword">const</span> wrapper <span class="token operator">=</span> <span class="token function">mount</span><span class="token punctuation">(</span>Posts<span class="token punctuation">,</span> <span class="token punctuation">{</span>
    store<span class="token punctuation">,</span>
    router<span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>

  wrapper<span class="token punctuation">.</span>vm<span class="token punctuation">.</span>$store<span class="token punctuation">.</span><span class="token function">commit</span><span class="token punctuation">(</span><span class="token string">'ADD_POSTS'</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token punctuation">{</span> id<span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">,</span> title<span class="token punctuation">:</span> <span class="token string">'Post'</span> <span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
  <span class="token keyword">await</span> wrapper<span class="token punctuation">.</span>vm<span class="token punctuation">.</span><span class="token function">$nextTick</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

  <span class="token function">expect</span><span class="token punctuation">(</span>wrapper<span class="token punctuation">.</span><span class="token function">findAll</span><span class="token punctuation">(</span><span class="token string">'.post'</span><span class="token punctuation">)</span><span class="token punctuation">.</span>length<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toBe</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre></div><h2 id="createwrapper-메서드-정의하기"><a href="#createwrapper-메서드-정의하기" class="header-anchor">#</a> <code>createWrapper</code> 메서드 정의하기</h2> <p>위 코드에서 이전 테스트와 수정된 상태를 비교했을 때 확실히 개선이 있었지만, 코드의 반 정도는 아직 중복된 것을 알 수 있습니다. 이 문제를 처리하기 위해서, <code>createWrapper</code>라는 새 메서드를 생성하겠습니다.</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">const</span> <span class="token function-variable function">createWrapper</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">component<span class="token punctuation">,</span> options <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> <span class="token punctuation">{</span> localVue<span class="token punctuation">,</span> store<span class="token punctuation">,</span> router <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token function">createTestVue</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token keyword">return</span> <span class="token function">mount</span><span class="token punctuation">(</span>component<span class="token punctuation">,</span> <span class="token punctuation">{</span>
    store<span class="token punctuation">,</span>
    router<span class="token punctuation">,</span>
    localVue<span class="token punctuation">,</span>
    <span class="token operator">...</span>options
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre></div><p>이제 <code>createWrapper</code>를 호출해서, 테스트할 컴포넌트의 새 복사본을 가지면 됩니다. 이제는 테스트가 매우 명료합니다.</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token function">it</span><span class="token punctuation">(</span><span class="token string">'통과하면 메시지를 렌더한다'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> message <span class="token operator">=</span> <span class="token string">'New content coming soon!'</span>
  <span class="token keyword">const</span> wrapper <span class="token operator">=</span> <span class="token function">createWrapper</span><span class="token punctuation">(</span>Posts<span class="token punctuation">,</span> <span class="token punctuation">{</span>
    propsData<span class="token punctuation">:</span> <span class="token punctuation">{</span> message <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>

  <span class="token function">expect</span><span class="token punctuation">(</span>wrapper<span class="token punctuation">.</span><span class="token function">find</span><span class="token punctuation">(</span><span class="token string">&quot;#message&quot;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">text</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toBe</span><span class="token punctuation">(</span><span class="token string">'New content coming soon!'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

<span class="token function">it</span><span class="token punctuation">(</span><span class="token string">'posts를 렌더한다'</span><span class="token punctuation">,</span> <span class="token keyword">async</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> wrapper <span class="token operator">=</span> <span class="token function">createWrapper</span><span class="token punctuation">(</span>Posts<span class="token punctuation">)</span>

  wrapper<span class="token punctuation">.</span>vm<span class="token punctuation">.</span>$store<span class="token punctuation">.</span><span class="token function">commit</span><span class="token punctuation">(</span><span class="token string">'ADD_POSTS'</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token punctuation">{</span> id<span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">,</span> title<span class="token punctuation">:</span> <span class="token string">'Post'</span> <span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
  <span class="token keyword">await</span> wrapper<span class="token punctuation">.</span>vm<span class="token punctuation">.</span><span class="token function">$nextTick</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

  <span class="token function">expect</span><span class="token punctuation">(</span>wrapper<span class="token punctuation">.</span><span class="token function">findAll</span><span class="token punctuation">(</span><span class="token string">'.post'</span><span class="token punctuation">)</span><span class="token punctuation">.</span>length<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toBe</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre></div><h2 id="초기-vuex-상태-설정하기"><a href="#초기-vuex-상태-설정하기" class="header-anchor">#</a> 초기 Vuex 상태 설정하기</h2> <p>우리가 할 마지막 개선은 어떻게 Vuex 스토어를 테스트에 붙일까에 대한 것입니다. 실제 애플리케이션에서는 스토어가 복잡할 수 있고, 테스트하기를 원하는 컴포넌트에 상태를 가지려고, 여러 가지 많은 뮤테이션(mutations)이나 액션(actions)을 <code>commit</code> 하거나 <code>dispatch</code> 하는 것은 이상적이지 않습니다.  <code>createStore</code> 함수에 약간의 변화를 줘서, 초기 상태를 더 쉽게 설정할 수 있도록 만들겠습니다.</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">const</span> <span class="token function-variable function">createStore</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">initialState <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token keyword">new</span> <span class="token class-name">Vuex<span class="token punctuation">.</span>Store</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  state<span class="token punctuation">:</span> <span class="token punctuation">{</span>
    authenticated<span class="token punctuation">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span>
    posts<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token operator">...</span>initialState
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  mutations<span class="token punctuation">:</span> <span class="token punctuation">{</span>
    <span class="token comment">// ...</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre></div><p>이제 <code>createStore</code> 함수를 원하는 초기 상태로 설정할 수 있습니다. 아래와 같이  <code>createTestVue</code>와 <code>createWrapper</code>를 머지해서 빠르게 리팩토링 할 수 있습니다.</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">const</span> <span class="token function-variable function">createWrapper</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">component<span class="token punctuation">,</span> options <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span> storeState <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> localVue <span class="token operator">=</span> <span class="token function">createLocalVue</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  localVue<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>VueRouter<span class="token punctuation">)</span>
  localVue<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>Vuex<span class="token punctuation">)</span>
  <span class="token keyword">const</span> store <span class="token operator">=</span> <span class="token function">createStore</span><span class="token punctuation">(</span>storeState<span class="token punctuation">)</span>
  <span class="token keyword">const</span> router <span class="token operator">=</span> <span class="token function">createRouter</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

  <span class="token keyword">return</span> <span class="token function">mount</span><span class="token punctuation">(</span>component<span class="token punctuation">,</span> <span class="token punctuation">{</span>
    store<span class="token punctuation">,</span>
    router<span class="token punctuation">,</span>
    localVue<span class="token punctuation">,</span>
    <span class="token operator">...</span>options
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre></div><p>이제 테스트는 아래와 같이 쓸 수 있습니다.</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token function">it</span><span class="token punctuation">(</span><span class="token string">'posts를 렌더한다'</span><span class="token punctuation">,</span> <span class="token keyword">async</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> wrapper <span class="token operator">=</span> <span class="token function">createWrapper</span><span class="token punctuation">(</span>Posts<span class="token punctuation">,</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span>
    posts<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token punctuation">{</span> id<span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">,</span> title<span class="token punctuation">:</span> <span class="token string">'Post'</span> <span class="token punctuation">}</span><span class="token punctuation">]</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>

  <span class="token function">expect</span><span class="token punctuation">(</span>wrapper<span class="token punctuation">.</span><span class="token function">findAll</span><span class="token punctuation">(</span><span class="token string">'.post'</span><span class="token punctuation">)</span><span class="token punctuation">.</span>length<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toBe</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre></div><p>큰 개선입니다! 코드의 절반가량이 보일러플레이트였던 테스트였고, 실제로 어설션(assertion)과 관련이 있지 않았습니다. 두 줄 중 한 줄은 컴포넌트 테스트를 준비하는 코드였고, 나머지 한 줄이 어설션을 위한 코드였습니다.</p> <p>이 리팩토링 작업의 덤은, 가지고 있는 모든 테스트에서 사용할 수 있는 유연한 <code>createWrapper</code> 함수를 얻었다는 것입니다.</p> <h2 id="개선사항"><a href="#개선사항" class="header-anchor">#</a> 개선사항</h2> <p>아래와 같은 몇 가지 잠재적인 개선사항이 있습니다.</p> <ul><li>Vuex의 namespaced 모듈의 초기 상태를 설정하도록 해주는 <code>createStore</code> 함수를 업데이트합니다</li> <li>특정 라우트를 설정하는 <code>createRouter</code>를 개선합니다</li> <li>사용자가 <code>createWrapper</code>에 <code>shallow</code>나 <code>mount</code> 인자를 넘기도록 해줍니다.</li></ul> <h2 id="결론"><a href="#결론" class="header-anchor">#</a> 결론</h2> <p>이 가이드 문서는 아래의 내용에 관해 얘기했습니다.</p> <ul><li>객체의 새 인스턴스를 얻는 팩토리 함수 사용</li> <li>일반적인 행동을 추출해서 보일러플레이트와 중복 줄이기</li></ul> <p>이 페이지에서 설명한 테스트의 소스 코드는 <a href="https://github.com/lmiller1990/vue-testing-handbook/tree/master/demo-app/tests/unit/Posts.spec.js" target="_blank" rel="noopener noreferrer">여기<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>에서 찾을 수 있습니다. <a href="https://vuejs-course.com/screencasts/reducing-duplication-in-tests.html?ref=vth" target="_blank" rel="noopener noreferrer">Vue.js Courses<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>에서 스크린캐스트로 이용할 수도 있습니다.</p></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/lmiller1990/vue-testing-handbook/edit/master/ko/reducing-boilerplate-in-tests.md" target="_blank" rel="noopener noreferrer">Github에서 이 페이지 수정하기</a> <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></div> <div class="last-updated"><span class="prefix">마지막 업데이트:</span> <span class="time">2020. 1. 27. 오후 6:02:09</span></div></footer> <div class="page-nav"><p class="inner"><span class="prev">
      ←
      <a href="/vue-testing-handbook/ko/composition-api.html" class="prev">컴포지션 API</a></span> <span class="next"><a href="/vue-testing-handbook/ko/jest-mocking-modules.html">Jest - 모듈 모킹하기</a>
      →
    </span></p></div> </main></div><div class="global-ui"></div></div>
    <script src="/vue-testing-handbook/assets/js/app.14051834.js" defer></script><script src="/vue-testing-handbook/assets/js/3.119a321e.js" defer></script><script src="/vue-testing-handbook/assets/js/2.94957ecd.js" defer></script><script src="/vue-testing-handbook/assets/js/38.2a809ae1.js" defer></script>
  </body>
</html>
